﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Reflection;
using System.Windows.Controls;
namespace CrazyWorship1
{
    public class State:IDisposable
    {
        public State(){
            _viewer = new List<Viewer>();
            SetupTransitions();
            SetupCreators();
            SetupControllers();
            SetupAssets();
        }
        public Transitions.BaseTransitionIn GetInTransition(string name)
        {
            if (inTransitions.ContainsKey(name))
                return (Transitions.BaseTransitionIn)Activator.CreateInstance(inTransitions[name]);
            else 
                throw new TransitionException("Transition Not Found: "+name);

        }
        public Transitions.BaseTransitionOut GetOutTransition(string name)
        {
            if (outTransitions.ContainsKey(name))
                return (Transitions.BaseTransitionOut)Activator.CreateInstance(outTransitions[name]);
            else
                throw new TransitionException("Transition Not Found");

        }
        public Transitions.BaseSongTransitionIn GetSongInTransition(string name)
        {
            if (inSongTransitions.ContainsKey(name))
                return (Transitions.BaseSongTransitionIn)Activator.CreateInstance(inSongTransitions[name]);
            else
                throw new TransitionException("Transition Not Found: " + name);
        }
        public Transitions.BaseSongTransitionOut GetSongOutTransition(string name)
        {
            if (outSongTransitions.ContainsKey(name))
                return (Transitions.BaseSongTransitionOut)Activator.CreateInstance(outSongTransitions[name]);
            else
                throw new TransitionException("Transition Not Found: " + name);
        }
        public Creators.CreateAllBase GetCreator(string name)
        {
            if (creators.ContainsKey(name))
                return (Creators.CreateAllBase)Activator.CreateInstance(creators[name]);
            else
                throw new TransitionException("Creator Not Found");

        }
        public Controllers.ControllerBase GetController(string name)
        {
            if (controllers.ContainsKey(name))
                return (Controllers.ControllerBase)Activator.CreateInstance(controllers[name]);
            else
                throw new TransitionException("Controller Not Found");

        }
        public Assets.AssetBase GetAsset(string name)
        {
            if (assets.ContainsKey(name))
                return (Assets.AssetBase)Activator.CreateInstance(assets[name]);
            else
                throw new TransitionException("Asset Not Found");

        }
        public Creators.CreateAllBase CurrentCreator
        {
            get
            {
                return GetCreator(CurrentSong.CreatorApp);
            }
        }
        void SetupCreators(){
            System.Reflection.Assembly a = Assembly.GetExecutingAssembly();
            creators = new Dictionary<String, Type>();
            foreach (Type t in a.GetTypes())
            {
                if (t.BaseType == typeof(Creators.CreateAllBase))
                    creators.Add(t.Name, t);
                
            }
        }
       public List<string> GetCreators()
        {
           List<string> ret=new List<string>();
           foreach (KeyValuePair<string,Type> a in creators){
                ret.Add(a.Key);
           }
           return ret;
        }
       public List<string> GetSongOutTransitions()
       {
           List<string> ret = new List<string>();
           foreach (KeyValuePair<string, Type> a in outSongTransitions)
           {
               ret.Add(a.Key);
           }
           return ret;
       }
       public List<string> GetSongInTransitions()
       {
           List<string> ret = new List<string>();
           foreach (KeyValuePair<string, Type> a in inSongTransitions)
           {
               ret.Add(a.Key);
           }
           return ret;
       }
       public List<string> GetInTransitions()
       {
           List<string> ret = new List<string>();
           foreach (KeyValuePair<string, Type> a in inTransitions)
           {
               ret.Add(a.Key);
           }
           return ret;
       }
       public List<string> GetOutTransitions()
       {
           List<string> ret = new List<string>();
           foreach (KeyValuePair<string, Type> a in outTransitions)
           {
               ret.Add(a.Key);
           }
           return ret;
       }

        void SetupControllers()
        {
            System.Reflection.Assembly a = Assembly.GetExecutingAssembly();
            controllers = new Dictionary<String, Type>();
            foreach (Type t in a.GetTypes())
            {
                if (t.BaseType == typeof(Controllers.ControllerBase))
                    controllers.Add(t.Name, t);

            }
        }
        void SetupAssets()
        {
            System.Reflection.Assembly a = Assembly.GetExecutingAssembly();
            assets = new Dictionary<String, Type>();
            foreach (Type t in a.GetTypes())
            {
                if (t.BaseType == typeof(Assets.AssetBase))
                    assets.Add(t.Name, t);

            }
        }
        Dictionary<String, Type> inTransitions,outTransitions,inSongTransitions,outSongTransitions,creators,controllers,assets;
       

        void SetupTransitions(){
            System.Reflection.Assembly a = Assembly.GetExecutingAssembly();// System.Reflection.Assembly.Load(System.AppDomain.CurrentDomain.BaseDirectory + "CrazyWorship1.exe");

            inTransitions = new Dictionary<String, Type>();
            outTransitions = new Dictionary<String, Type>();
            inSongTransitions = new Dictionary<String, Type>();
            outSongTransitions = new Dictionary<String, Type>();
            foreach (Type t in a.GetTypes())
            {
                if (t.BaseType == typeof(Transitions.BaseTransitionIn))
                    inTransitions.Add(t.Name, t);
                if (t.BaseType == typeof(Transitions.BaseTransitionOut))
                    outTransitions.Add(t.Name, t);
                if (t.BaseType == typeof(Transitions.BaseSongTransitionIn))
                    inSongTransitions.Add(t.Name, t);
                if (t.BaseType == typeof(Transitions.BaseSongTransitionOut))
                    outSongTransitions.Add(t.Name, t);
            }

            
        }
        public void LoadDB()
        {
            DataUtils.CreateDefaultSongDB();
            SongDB = DataUtils.LoadSongDB();
        }
        private SongDB _songDB;
        private SongDB.SongsRow _currentSong;
        private DataView _currentLyrics;
        private SongDB.LyricsRow _currentLyric;
        private SongDB.LyricsRow _previousLyric;
        public DataView CurrentLyrics
        {
            get
            {
                return _currentLyrics;
            }
         
        }
        
        public SongDB.SongsRow CurrentSong
        {
            get
            {
                return _currentSong;
            }
           
        }
        SongDB.SongsRow _nextSong;
        public void SetNextSong(SongDB.SongsRow r)
        {
            if (_currentSong == null)
            {
                _currentSong = r;
                SongChanged();
            }
            else
            {
                _nextSong = r;
                StartSongChange();
            }
        }
        public void StartNextSong()
        {
            _currentSong = _nextSong;
            _currentLyric = null;
            _previousLyric = null;
            SongChanged();
        }
       

        
        public SongDB SongDB
        {
            get
            {
                return _songDB;
            }
            set
            {
                _songDB = value;
                SongDBChanged();
            }
        }
        public DataView SongsOrderedByName
        {
            get
            {
                DataView dv = _songDB.Songs.DefaultView;
                dv.Sort = "Name";
                return dv;
            }
        }
        public SongDB.LyricsRow CurrentLyric
        {
            get
            {
                return _currentLyric;
            }
            set
            {
                PreviousLyric = _currentLyric;
                _currentLyric = value;
                LyricChanged();
            }
        }
        public SongDB.LyricsRow PreviousLyric
        {
            get
            {
                return _previousLyric;
            }
            set
            {
                _previousLyric = value;
               
            }
        }
        List<Viewer> _viewer;
        public List<Viewer> Viewers
        {
            get
            {
                return _viewer;
            }
         
        }
        public void LyricChanged()
        {
            if (OnLyricChanged != null)
                OnLyricChanged(this, new EventArgs());
        }
        public void SongChanged(){
            _currentLyrics = new System.Data.DataView(SongDB.Lyrics, "SongID='" + CurrentSong.SongID.ToString() + "'", "Order", System.Data.DataViewRowState.CurrentRows);
            if (OnSongChanged != null)
                OnSongChanged (this, new EventArgs());
        }
        public void StartSongChange()
        {
            if (OnStartSongChange != null)
                OnStartSongChange(this, new EventArgs());
        }
        public void SongDBChanged()
        {
            if (OnSongDBChanged != null)
                OnSongDBChanged(this, new EventArgs());
        }
        public event EventHandler OnLyricChanged;
        public event EventHandler OnSongChanged;
        public event EventHandler OnStartSongChange;
        public event EventHandler OnSongDBChanged;


        #region IDisposable Members

        public void Dispose()
        {
            Dispose(true);
            // This object will be cleaned up by the Dispose method.
            // Therefore, you should call GC.SupressFinalize to
            // take this object off the finalization queue
            // and prevent finalization code for this object
            // from executing a second time.
            GC.SuppressFinalize(this);
        }

        // Dispose(bool disposing) executes in two distinct scenarios.
        // If disposing equals true, the method has been called directly
        // or indirectly by a user's code. Managed and unmanaged resources
        // can be disposed.
        // If disposing equals false, the method has been called by the
        // runtime from inside the finalizer and you should not reference
        // other objects. Only unmanaged resources can be disposed.
        private bool disposed;

        private void Dispose(bool disposing)
        {
            // Check to see if Dispose has already been called.
            if (!this.disposed)
            {
                // If disposing equals true, dispose all managed
                // and unmanaged resources.
                if (disposing)
                {
                    // Dispose managed resources.
                    _currentLyrics.Dispose();
                }

                // Call the appropriate methods to clean up
                // unmanaged resources here.
                // If disposing is false,
                // only the following code is executed.
            //    CloseHandle(handle);
           //     handle = IntPtr.Zero;

                // Note disposing has been done.
                disposed = true;

            }
        }

        #endregion
    }
}
